#!/usr/bin/env python
#
# sm_syslog.py
#
# Version : 0.4
# Date : 20070709
#
# Author : Bernard Czenkusz
# Email  : bernie@skipole.co.uk

#
# sm_syslog.py - sends syslog messages, run as part of skipolemonitor
# Copyright (c) 2007 Bernard Czenkusz
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#

"""Sends syslog messages; a module of Skipole Monitor

create_logger() called from monitor.py to create the logger
send_syslogs() called from poller.py to send any required syslog messages.

Configuration values, such as the syslog server, are provided by the net module.

gui_edit.py also uses this module to send test logs, and to stop the logger
and create a new logger, should the service be changed by the user.
"""


import logging
import socket
import logging.handlers
from net import *

# LOGGER_RUNNING is 0 if the syslog logger has not yet been created, it becomes 1
# once it is created and running
LOGGER_RUNNING=0
# These global values are initially None, until the logger is created
rootLogger=None
LogHandler=None


def create_logger():
    """Create the syslog logger"""
    global net_cfg
    global LOGGER_RUNNING
    global rootLogger
    global LogHandler
    # If already started, return
    if LOGGER_RUNNING == 1: return 1
    if net_cfg["GROUP_SYSLOG_ENABLED"] == "0" and net_cfg["HOST_SYSLOG_ENABLED"] == "0":
        return 1
    if net_cfg["SYSLOG_SERVER"] == "not.set" : return 1
    # syslog server ip address and UDP port number
    server_address=(net_cfg["SYSLOG_SERVER"], int(net_cfg["SYSLOG_PORT"]))
    try:
        rootLogger = logging.getLogger('')
        rootLogger.setLevel(logging.WARNING)

        # create a syslog Filhandler
        LogHandler = logging.handlers.SysLogHandler(server_address, int(net_cfg["SYSLOG_FACILITY"]))

        # add the handler to the root logger
        rootLogger.addHandler(LogHandler)
    except:
        return 0
    # logger created, so set global flag
    LOGGER_RUNNING=1
    return 1


def stop_logger():
    """Stop the syslog logger"""
    global net_cfg
    global LOGGER_RUNNING
    global rootLogger
    global LogHandler
    # If already stopped, return
    if LOGGER_RUNNING == 0: return
    rootLogger.removeHandler(LogHandler)
    LogHandler.close()
    LOGGER_RUNNING = 0
    return


def send_syslogs():
    """If syslog alerting is enabled, send any necessary alerts"""
    global net_cfg
    global LOGGER_RUNNING
    # If the logger is not running, then logs cannot be sent, just return
    if LOGGER_RUNNING == 0 : return
    # Check if syslog is globally enabled.
    if net_cfg["GROUP_SYSLOG_ENABLED"] == "0" and net_cfg["HOST_SYSLOG_ENABLED"] == "0":
        return
    if net_cfg["SYSLOG_SERVER"] == "not.set" : return
    # Check syslog server name is resolvable
    try:
        socket.gethostbyname(net_cfg["SYSLOG_SERVER"])
    except:
        return
    #
    # for each item, if its status has changed, then send a syslog message
    for id in network(0):
        msg_contents="Skipole Monitor : "
        new_status=get_net(id, STATUS)
        old_status=get_net(id, OLDSTATUS)
        # If the status of this item has not changed, continue to the next
        if new_status == old_status: continue
        # if the status change is from white (unknown) to green (ok) - don't send message
        if old_status==0 and new_status==1: continue
        # If device is a group, check group syslog enabled
        if get_net(id, ADDRESS) == "0" :
            if net_cfg["GROUP_SYSLOG_ENABLED"] == "0" : continue
            msg_contents += "Status of group %s " % get_net(id, NAME)
        else:
            # Device is a host, check host syslog enabled
            if net_cfg["HOST_SYSLOG_ENABLED"] == "0" : continue
            msg_contents += "Status of host %s (%s) " % (get_net(id, NAME), get_net(id, ADDRESS))
        if old_status == 0:
            msg_contents += "has changed from unknown (White) to "
        if old_status == 1:
            msg_contents += "has changed from OK (Green) to "
        if old_status == 2:
            msg_contents += "has changed from partial failure (Yellow) to "
        if old_status == 3:
            msg_contents += "has changed from Fail (Red) to "
        if new_status == 0:
            msg_contents += "unknown (White)"
        if new_status == 1:
            msg_contents += "OK (Green)"
        if new_status == 2:
            msg_contents += "partial failure (Yellow)"
        if new_status == 3:
            msg_contents += "Fail (Red)"
        # send the syslog message
        try:
            if LOGGER_RUNNING == 1 :
                logging.warning(msg_contents)
        except:
            # If it fails, dont create errors, carry on with rest of
            # the program, accepting this part won't work
            break
    return
